package com.cf.pay.core.wx;

import com.cf.constant.EnumReturnCode;
import com.cf.exception.BizException;
import com.cf.util.HttpUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;

/**
 * wx-hongbao-WxPayService
 *
 * @author <a href="2428922347@qq.com">Zhu mingming</a>
 * @info 微信支付服务接口
 * @since 2018/1/16 15:27
 */
@Slf4j
public class WxPayService {

    /**
     * 微信小程序支付
     *
     * @param wxPayProperty
     * @param ip
     * @param openId
     * @param orderId
     * @param money         分
     * @param payName
     * @return
     */
    private static WxPayBean xcxPay(WxPayProperty wxPayProperty, String ip, String openId, String orderId, long money, String payName) {
        return xcxPay(wxPayProperty, ip, openId, orderId, String.valueOf(money), payName);
    }

    /**
     * 微信小程序支付
     *
     * @param wxPayProperty
     * @param ip
     * @param openId
     * @param orderId
     * @param money
     * @param payName
     * @return
     */
    private static WxPayBean xcxPay(WxPayProperty wxPayProperty, String ip, String openId, String orderId, String money, String payName) {
        try {
            //生成的随机字符串
            String nonce_str = SecurityUtil.getRandomString(16);

            //组装参数，用户生成统一下单接口的签名
            Map<String, String> packageParams = new HashMap();
            packageParams.put("appid", wxPayProperty.getAppId());
            packageParams.put("mch_id", wxPayProperty.getMchId());
            packageParams.put("nonce_str", nonce_str);
            packageParams.put("body", payName);
            packageParams.put("out_trade_no", orderId);//商户订单号
            packageParams.put("total_fee", money);//支付金额，这边需要转成字符串类型，否则后面的签名会失败
            packageParams.put("spbill_create_ip", ip);
            packageParams.put("notify_url", wxPayProperty.getNotifyUrl());//支付成功后的回调地址
            packageParams.put("trade_type", wxPayProperty.getTradeType());//支付方式
            packageParams.put("openid", openId);

            //MD5运算生成签名，这里是第一次签名，用于调用统一下单接口
            String mysign = PayUtil.sign(PayUtil.createLinkString(packageParams), wxPayProperty.getKey(), "utf-8").toUpperCase();

            //拼接统一下单接口使用的xml数据，要将上一步生成的签名一起拼接进去
            String xml = "<xml>" + "<appid>" + wxPayProperty.getAppId() + "</appid>"
                    + "<body><![CDATA[" + payName + "]]></body>"
                    + "<mch_id>" + wxPayProperty.getMchId() + "</mch_id>"
                    + "<nonce_str>" + nonce_str + "</nonce_str>"
                    + "<notify_url>" + wxPayProperty.getNotifyUrl() + "</notify_url>"
                    + "<openid>" + openId + "</openid>"
                    + "<out_trade_no>" + orderId + "</out_trade_no>"
                    + "<spbill_create_ip>" + ip + "</spbill_create_ip>"
                    + "<total_fee>" + money + "</total_fee>"
                    + "<trade_type>" + wxPayProperty.getTradeType() + "</trade_type>"
                    + "<sign>" + mysign + "</sign>"
                    + "</xml>";
            //调用统一下单接口，并接受返回的结果
            String result = HttpUtil.post("https://api.mch.weixin.qq.com/pay/unifiedorder", xml);
            // 将解析结果存储在HashMap中
            Map map = PayUtil.doXMLParse(result);
            String return_code = (String) map.get("return_code");//返回状态码

            if ("SUCCESS".equals(return_code)) {
                String prepay_id = (String) map.get("prepay_id");//返回的预付单信息
                Long timeStamp = System.currentTimeMillis() / 1000;
                String stringSignTemp = "appId=" + wxPayProperty.getAppId() + "&nonceStr=" + nonce_str + "&package=prepay_id=" + prepay_id + "&signType=MD5&timeStamp=" + timeStamp;
                //再次签名，这个签名用于小程序端调用wx.requesetPayment方法
                String paySign = PayUtil.sign(stringSignTemp, wxPayProperty.getKey(), "utf-8").toUpperCase();
                return new WxPayBean(nonce_str, "prepay_id=" + prepay_id, timeStamp.toString(), paySign, wxPayProperty.getAppId());
            } else {
                throw new
                        BizException(EnumReturnCode.ERROR.getCode(), result);
            }
        } catch (Exception e) {
            throw new BizException(EnumReturnCode.ERROR.getCode(), "微信支付异常！", e);
        }
    }
}
